// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rainbowchat.http.logic.dto;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import com.eva.epc.common.util.CommonUtils;

/**
 * 时间显示工具类。本类可用于标准Java和Andriod平台中。
 * 
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @since 7.1
 */
public class TimeToolKit 
{
	/**
	 * 传入秒数，得到“mm:ss”样的字符串。
	 * 目前主要用于Andriod端显示短视频的视频时长时使用，本方法也可用于任何标准Java的代码中。
	 * 
	 * @param durationWithSecond 秒数
	 * @return 形如“0:10”这样的字符串，表示10秒时长的短视频
	 * @since 7.1
	 */
	public static String getMMSSFromSS(int durationWithSecond)
	{
		if(durationWithSecond < 0){
			return "00:00";
		}

		//format of minute
		String str_minute = String.format("%d", durationWithSecond / 60);
		//format of second
		String str_second = String.format("%02d", durationWithSecond % 60);
		//format of time
		String format_time = str_minute + ":" + str_second;
		return format_time;
	}

	/**
	 * 不带时区信息的时间戳按当前默认时代转换成时间字串显示。
	 * 
	 * @param timestampWithGMT 本时间戳为GMT标准时间，解决跨国跨时区问题，用于UI时客户端需要转换成自已
	 * 的时区后再使用哦，此字段存放的是java版无时间时间戳，形如：1510491984536） 
	 * @param timePattern 要转换的目标时间字串格式
	 * @return 如果转换成功则返回指定样式的时间字串，否则返回""
	 */
	public static String convertTimstampToDefaultTimeZone(String timestampWithGMT, String timePattern)
	{
		String dateTimeStrForDefaultZone = "";
		if(timestampWithGMT != null)
			dateTimeStrForDefaultZone = getTimeString(getDateTime(timestampWithGMT), timePattern);
		
		return dateTimeStrForDefaultZone;
	}
	
	/**
	 * 返回指定pattern样的日期时间字符串。
	 * 
	 * @param dt
	 * @param pattern
	 * @return 如果时间转换成功则返回结果，否则返回空字符串""
	 */
	public static String getTimeString(Date dt, String pattern)
	{
		try
		{
			SimpleDateFormat sdf = new SimpleDateFormat(pattern);//"yyyy-MM-dd HH:mm:ss"
			sdf.setTimeZone(TimeZone.getDefault());
			return sdf.format(dt);
		}
		catch (Exception e)
		{
			return "";
		}
	}
	
	/**
	 * 将指定字符串时间戳转为Date对象。
	 * 
	 * @param timestampWithGMT 本时间戳为GMT标准时间，解决跨国跨时区问题，用于UI时客户端需要转换成自已
	 * 的时区后再使用哦，此字段存放的是java版无时间时间戳，形如：1510491984536） 
	 * @return
	 */
	public static Date getDateTime(String timestampWithGMT)
	{
		return getDateTime(CommonUtils.getLongValue(timestampWithGMT));
	}
	public static Date getDateTime(long timestampWithGMT)
	{
		return new Date(timestampWithGMT);
	}
	
	/**
	 * 显示一个人性化的时间字串（本方法当前主要用于客户界面的消息时间显示时）。
	 * <p>
	 * 当此时间是当天时间则显示“时分”格式，如果是当年则显示“月时分”格式，如果是
	 * 今年之前的则显示为“年月时分”格式。
	 * <p>
	 * 本方法当前主要用于Android客户端首页“消息界面”中显示离线消息的时间之用，目
	 * 的是让时间显示尽可能短且人性化，仅此而已。
	 * 
	 * @param dt NSDate对象
	 * @return 如果转换成功则返回形如：“刚刚”、“12:01"、“03-01 12：01”、“2018-02-01 12：01”，否则返回""
	 * @deprecated by {@link OfflineMsgDTO#getTimeStringAutoShort2(Date, boolean)}, @since 4.5
	 */
	public static String getTimeStringAutoShort(Date srcDate)
	{
		String ret = "";
		
		try
		{
			GregorianCalendar gcCurrent = new GregorianCalendar();
			gcCurrent.setTime(new Date());
			int currentYear = gcCurrent.get(GregorianCalendar.YEAR);
			int currentMonth = gcCurrent.get(GregorianCalendar.MONTH);
			int currentDay = gcCurrent.get(GregorianCalendar.DAY_OF_MONTH);
//			System.out.println("【DEBUG-getTimeStringAutoShort】currentDate = "+gcCurrent.getTime().toLocaleString()
//					+" ,year = "+currentYear+" ,month="+currentMonth+", day="+currentDay);
			
			GregorianCalendar gcSrc = new GregorianCalendar();
			gcSrc.setTime(srcDate);
			int srcYear = gcSrc.get(GregorianCalendar.YEAR);
			int srcMonth = gcSrc.get(GregorianCalendar.MONTH);
			int srcDay = gcSrc.get(GregorianCalendar.DAY_OF_MONTH);
//			System.out.println("【DEBUG-getTimeStringAutoShort】gcSrc = "+gcSrc.getTime().toLocaleString()
//					+" ,year = "+srcYear+" ,month="+srcMonth+", day="+srcDay);
			
			// 当年
			if(currentYear == srcYear)
		    {
				long currentTimestamp = gcCurrent.getTimeInMillis();
		        long srcTimestamp = gcSrc.getTimeInMillis();

		        // 相差时间（单位：毫秒）
		        long delta = currentTimestamp - srcTimestamp;
				
		        // 当天
		        if(currentMonth == srcMonth && currentDay == srcDay)
		        {
		        	// 时间相差60秒以内
		            if(delta < 60 * 1000)
		                ret = "刚刚";
		            else
		            	ret = getTimeString(srcDate, "HH:mm");
		        }
		        // 当年 && 当天之外的时间
		        else
		        {
		        	 if ((delta/(3600 * 1000)) > 24 && (delta/(3600 * 1000)) < 48)
		                 ret = "昨天";
		             else if ((delta/(3600 * 1000)) > 48 && (delta/(3600 * 1000)) < 72)
		                 ret = "前天";
		             else
		            	 ret = getTimeString(srcDate, "M/d");
		        }
		    }
		    else
		    	ret = getTimeString(srcDate, "yy/M/d HH:mm");
			
//			System.out.println("【DEBUG-getTimeStringAutoShort】计算结果："+ret+" 【OK】");
		}
		catch (Exception e)
		{
			System.err.println("【DEBUG-getTimeStringAutoShort】计算出错："+e.getMessage()+" 【NO】");
		}
		
		return ret;
	}
	
	/**
     * 仿照微信中的消息时间显示逻辑，将时间戳（单位：毫秒）转换为友好的显示格式.
     * <p>
     * 1）7天之内的日期显示逻辑是：今天(具体的“时间:分钟”样式)、昨天(-1d)、前天(-2d)、星期？（只显示总计7天之内的星期数，即<=-4d）；<br>
     * 2）7天之外（即>7天）的逻辑：当年(显示“M月/d日”)、去年及之前(显示“yy年/M月/d日”)。
     *
     * @param srcDate 要处理的源日期时间对象
     * @param mustIncludeTime true表示输出的格式里一定会包含“时间:分钟”（如果是“当天”，则不受此参数控制，无条件包含时间分钟），否则不包含（参考微信，不包含时分的情况，用于首页“消息”中显示时）
     * @param timeWithSegmentStr 本参数仅在mustIncludeTime=true时有生效，表示在时间字符串前带上“上午”、“下午”、“晚上”这样的描述
     * @return 输出格式形如：“上午10:30”、“昨天 中午12:04”、“前天 晚上20:51”、“星期二 上午09:30”、“5月6日 上午11:09”、“20年5月6日 上午11:09”等形式
     * @since 4.5
     */
	public static String getTimeStringAutoShort2(Date srcDate, boolean mustIncludeTime, boolean timeWithSegmentStr)
	{
		String ret = "";
		
		try
		{
			boolean isChineseLanguage = isChineseLanguage();
			
			GregorianCalendar gcCurrent = new GregorianCalendar();
			gcCurrent.setTime(new Date());
			int currentYear = gcCurrent.get(GregorianCalendar.YEAR);
			int currentMonth = gcCurrent.get(GregorianCalendar.MONTH)+1;
			int currentDay = gcCurrent.get(GregorianCalendar.DAY_OF_MONTH);
//			System.out.println("【DEBUG-getTimeStringAutoShort】currentDate = "+gcCurrent.getTime().toLocaleString()
//					+" ,year = "+currentYear+" ,month="+currentMonth+", day="+currentDay);
			
			GregorianCalendar gcSrc = new GregorianCalendar();
			gcSrc.setTime(srcDate);
			int srcYear = gcSrc.get(GregorianCalendar.YEAR);
			int srcMonth = gcSrc.get(GregorianCalendar.MONTH)+1;
			int srcDay = gcSrc.get(GregorianCalendar.DAY_OF_MONTH);
//			System.out.println("【DEBUG-getTimeStringAutoShort】gcSrc = "+gcSrc.getTime().toLocaleString()
//					+" ,year = "+srcYear+" ,month="+srcMonth+", day="+srcDay);
			
			// 要额外显示的时间分钟
			String timeExtraStr = "";
			if(mustIncludeTime)
			{
//				String timePattern = "HH:mm";
//				// 原始的时间分钟字符串
//				String timeExtraStrOriginal = getTimeString(srcDate, timePattern);
//				
//				// 时间段描述（形如：“上午”、“下午”、“晚上”这样的描述），只在中文语言下生效
//				String timeSegmentStr = "";
//				if(timeWithSegmentStr)
//					timeSegmentStr = isChineseLanguage?getTimeSegmentStr(timeExtraStrOriginal):"";
//					
//				// 组合成最终的人性化时间分钟字符串形式
//				timeExtraStr = " "+timeSegmentStr+timeExtraStrOriginal;
				
				timeExtraStr = " "+getTimeHH24Human(srcDate, timeWithSegmentStr);
			}
	        
			// 当年
			if(currentYear == srcYear)
		    {
				long currentTimestamp = gcCurrent.getTimeInMillis();
		        long srcTimestamp = gcSrc.getTimeInMillis();

		        // 相差时间（单位：毫秒）
		        long delta = (currentTimestamp - srcTimestamp);
				
		        // 当天（月份和日期一致才是）
		        if(currentMonth == srcMonth && currentDay == srcDay)
		        {
//		        	// 时间相差60秒以内
//	                if(delta < 60 * 1000)
//	                    ret = "刚刚";
//	                // 否则当天其它时间段的，直接显示“时:分”的形式
//	                else
//	                    ret = getTimeString(srcDate, "HH:mm");
		        	
		        	// 当天只需要显示时间分钟，且必须显示“上午”、“下午”这样的时间段描述
		        	ret = getTimeHH24Human(srcDate, true);
		        }
		        // 当年 && 当天之外的时间（即昨天及以前的时间）
		        else
		        {
		        	// 昨天（以“现在”的时候为基准-1天）
		        	GregorianCalendar yesterdayDate = new GregorianCalendar();
	                yesterdayDate.add(GregorianCalendar.DAY_OF_MONTH, -1);

	                // 前天（以“现在”的时候为基准-2天）
	                GregorianCalendar beforeYesterdayDate = new GregorianCalendar();
	                beforeYesterdayDate.add(GregorianCalendar.DAY_OF_MONTH, -2);
		        	
	                // 用目标日期的“月”和“天”跟上方计算出来的“昨天”进行比较，是最为准确的（如果用时间戳差值
	                // 的形式，是不准确的，比如：现在时刻是2019年02月22日1:00、而srcDate是2019年02月21日23:00，
	                // 这两者间只相差2小时，直接用“delta/(3600 * 1000)” > 24小时来判断是否昨天，就完全是扯蛋的逻辑了）
	                if(srcMonth == (yesterdayDate.get(GregorianCalendar.MONTH)+1) 
	                		&& srcDay == yesterdayDate.get(GregorianCalendar.DAY_OF_MONTH))
	                {
	                    ret = "昨天"+timeExtraStr;// -1d
	                }
	                // “前天”判断逻辑同上
	                else if(srcMonth == (beforeYesterdayDate.get(GregorianCalendar.MONTH)+1) 
	                		&& srcDay == beforeYesterdayDate.get(GregorianCalendar.DAY_OF_MONTH))
	                {
	                    ret = "前天"+timeExtraStr;// -2d
	                }
	                else
	                {
	                    // 跟当前时间相差的小时数
	                    long deltaHour = (delta/(3600 * 1000));

	                    // 如果小于 7*24小时就显示星期几
	                    if (deltaHour < 7*24)
	                    {
	                        String[] weekday = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};

	                        // 取出当前是星期几
	                        String weedayDesc = weekday[gcSrc.get(GregorianCalendar.DAY_OF_WEEK)-1];
	                        ret = weedayDesc+timeExtraStr;
	                    }
	                    // 否则直接显示完整日期时间
	                    else
	                        ret = getTimeString(srcDate, (isChineseLanguage()?"M月d日":"M/d"))+timeExtraStr;
	                }
		        }
		    }
		    else
		    	ret = getTimeString(srcDate, (isChineseLanguage?"yy年M月d日":"yy/M/d"))+timeExtraStr;
			
//			System.out.println("【DEBUG-getTimeStringAutoShort】计算结果："+ret+" 【OK】");
		}
		catch (Exception e)
		{
			System.err.println("【DEBUG-getTimeStringAutoShort】计算出错："+e.getMessage()+" 【NO】");
		}
		
		return ret;
	}
	
	/**
	 * 获取仅包含“时间:分钟”部分的字符串，24小时制，且可以显示“上午”、“下午”、“晚上”这样的描述。
	 * 
	 * @param srcDate
	 * @param timeWithSegmentStr 表示在时间字符串前带上“上午”、“下午”、“晚上”这样的描述
	 * @return 如果成功则返回结果，否则返回空字符串（不是null）
	 */
	private static String getTimeHH24Human(Date srcDate, boolean timeWithSegmentStr)
	{
		String ret = "";
		
		try {
			String timePattern = "HH:mm";
			// 原始的时间分钟字符串
			String timeStr = getTimeString(srcDate, timePattern);
			
			// 时间段描述（形如：“上午”、“下午”、“晚上”这样的描述），只在中文语言下生效
			String timeSegmentStr = "";
			if(timeWithSegmentStr)
				timeSegmentStr = (isChineseLanguage()?getTimeSegmentStr(timeStr):"");
				
			// 组合成最终的人性化时间分钟字符串形式
			ret = timeSegmentStr+timeStr;
		} catch (Exception e) {
			System.err.println("【DEBUG-getTimeHH24Human】计算出错："+e.getMessage()+" 【NO】");
		}
		
		return ret;
	}
	
	/**
	 * 将一个两位24小时时间的转换为上午、下午这样的描述。
	 * 
	 * @param hh24 两位的24小时制时间的小时部分
	 * @return 如果成功转换则返回形如：“凌晨”、“上午”等，否则返回空字符串（不是null）
	 * @since 7.1
	 */
	private static String getTimeSegmentStr(String hh24)
	{
		String ret = "";
		if(hh24 != null && hh24.length()>=2)
		{
			try {
				// 取出“小时”部分
				int a = Integer.parseInt(hh24.substring(0, 2));
		        if (a >= 0 && a <= 6) {
		        	ret = "凌晨";
		        }
		        else if (a > 6 && a <= 12) {
		        	ret = "上午";
		        }
		        else if (a > 12 && a <= 13) {
		        	ret = "中午";
		        }
		        else if (a > 13 && a <= 18) {
		        	ret = "下午";
		        }
		        else if (a > 18 && a <= 24) {
		        	ret = "晚上";
		        }
			} catch (Exception e) {
				System.err.println("【DEBUG-getTimeSegmentStr】计算出错："+e.getMessage()+" 【NO】");
			}
		}
		
		return ret;
	}
	
	/**
	 *  判断当前系统语言是否是中文。
	 * 
	 * @return true表示是是中文环境（不区分简繁体，否则不是）
	 * @since 7.1
	 */
	private static boolean isChineseLanguage()
	{
		boolean is = true;
		try {
			is = (Locale.getDefault().getLanguage().equals(new Locale("zh").getLanguage()));
		} catch (Exception e) {
			System.err.println("【DEBUG-isChineseLanguage】"+e.getMessage());
		}
		return is;
	}
	
	public static void main(String[] args) throws Exception
	{
//		String ddd = "2019-02-22 19:50";
//		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
//		Date d = sdf.parse(ddd);
//		
//		System.out.println("结果："+OfflineMsgDTO.getTimeStringAutoShort2(d, true));
		
//		System.out.println(""+OfflineMsgDTO.isChineseLanguage());
		
//		System.out.println(new SimpleDateFormat("yyyy-MM-dd aHH:mm:ss").format(new Date()));
//		
//		SimpleDateFormat sdf = new SimpleDateFormat("HH");//"yyyy-MM-dd HH:mm:ss"
//		sdf.setTimeZone(TimeZone.getDefault());
//		System.out.println(getTimeSegmentStr("23"));
		
//		System.out.println(getTimeHH24Human(new Date(), true));
		
//		System.out.println(TTT.getMMSSFromSS(6));
	}
	
}
